package com.educatioin.manage.wechat.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.educatioin.manage.common.beans.Response;
import com.educatioin.manage.constant.OrderStatus;
import com.educatioin.manage.constant.WeChatApiConstant;
import com.educatioin.manage.utils.WeChatUriUtil;
import com.educatioin.manage.web.productorder.po.ProductOrderPo;
import com.educatioin.manage.web.productorder.repository.ProductOrderRepository;
import com.educatioin.manage.wechat.dto.WeChatThirdTokenRespDto;
import com.educatioin.manage.wechat.response.PayOrderRsp;
import com.educatioin.manage.wechat.service.WeChatApiService;
import com.educatioin.manage.wechat.service.WeChatOrderService;
import com.github.wxpay.sdk.WXPayUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Objects;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Created by zhangchen on 2018/3/7.
 */
@RestController
@RequestMapping("/wx/api")
public class WeChatApiController {

    private static Logger logger = LoggerFactory.getLogger(WeChatApiController.class);

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private WeChatApiService weChatApiService;
    @Autowired
    private WeChatOrderService weChatOrderService;
    @Autowired
    private ProductOrderRepository productOrderRepository;


    /**
     * WX接口配置信息
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String wx(@RequestParam(name="signature")String signature,
                        @RequestParam(name="timestamp")String timestamp,
                        @RequestParam(name="nonce")String nonce,
                        @RequestParam(name="echostr")String echostr) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        //排序
        String sortString = sort(WeChatApiConstant.TOKEN, timestamp, nonce);
        //加密
        String myString = sha1(sortString);
        //校验
        if (myString != null && myString != "" && myString.equals(signature)) {
            //如果检验成功原样返回echostr，微信服务器接收到此输出，才会确认检验完成。
            return echostr;
        } else {
            return "";
        }
    }

    /**
     * 微信jssdk证书获取
     * @param
     * @return signature
     * @throws IOException
     */
    @RequestMapping(value = "/signature", method = RequestMethod.GET)
    @ResponseBody
    public String createSignature(@RequestParam String url) throws IOException{

        logger.info("RestFul of createSignature parameters url:{}",url);

        try {
            String rs = weChatApiService.createSignature(url);
            return rs;
        } catch (Exception e) {
            logger.error("RestFul of signature is error.",e);
        }

        return null;
    }

    @RequestMapping(value="/openid", method = RequestMethod.GET)
    public String getOpenid(@RequestParam(value="code") String code, @RequestParam(value="state") String state) {
        if (StringUtils.isBlank(state)|| !state.startsWith(WeChatApiConstant.CODE_STATE)){
            return null;
        }

        String tokenUrl = WeChatUriUtil.getWebAccess(WeChatApiConstant.APP_ID, WeChatApiConstant.APP_SECRET, code);

        String weChatThirdTokenStr  = restTemplate.getForObject(tokenUrl, String.class);
        if(StringUtils.isBlank(weChatThirdTokenStr)) {
            return null;
        }

        WeChatThirdTokenRespDto weChatThirdTokenResp = JSON.parseObject(weChatThirdTokenStr, WeChatThirdTokenRespDto.class);

        if (null != weChatThirdTokenResp.getErrcode()){
            return null;
        }
        return weChatThirdTokenResp.getOpenid();
    }

    @RequestMapping(value="/jspay")
    public PayOrderRsp jsPay(String orderCode) throws Exception {
        ProductOrderPo productOrderPo = productOrderRepository.findByOrderCode(orderCode);
        PayOrderRsp payOrderRsp = new PayOrderRsp();
        if(!Objects.equals(productOrderPo.getOrderStatus(), OrderStatus.UN_PAYED.name())){
            payOrderRsp.setReturnCode(Response.RETURN_FAIL_CODE);
            payOrderRsp.setReturnMsg("订单已支付");
            return payOrderRsp;
        }
        boolean success = weChatOrderService.getPrepaidIdByOder(productOrderPo);
        if(!success){
            payOrderRsp.setReturnCode(Response.RETURN_FAIL_CODE);
            payOrderRsp.setReturnMsg("订单微信预付失败");
            return payOrderRsp;
        }

        //获取预付id
        String prepayId = productOrderPo.getPrepayId();
        SortedMap<String, String> payMap = new TreeMap<>();
        payMap.put("appId", WeChatApiConstant.APP_ID);
        payMap.put("timeStamp", WeChatApiService.create_timestamp());
        payMap.put("nonceStr", WeChatApiService.create_nonce_str());
        payMap.put("signType", "MD5");
        payMap.put("package", "prepay_id=" + prepayId);
        String sign = WXPayUtil.generateSignature(payMap, WeChatApiConstant.MCH_KEY);
        payMap.put("paySign", sign);
        payOrderRsp.setPhone(productOrderPo.getPhone());
        payOrderRsp = JSON.parseObject(JSONObject.toJSONString(payMap), PayOrderRsp.class);
        return payOrderRsp;
    }

    /**
     * 排序方法
     */
    public String sort(String token, String timestamp, String nonce) {
        String[] strArray = {token, timestamp, nonce};
        Arrays.sort(strArray);
        StringBuilder sb = new StringBuilder();
        for (String str : strArray) {
            sb.append(str);
        }

        return sb.toString();
    }

    /**
     * 将字符串进行sha1加密
     *
     * @param str 需要加密的字符串
     * @return 加密后的内容
     */
    public String sha1(String str) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(str.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
}
